package com.elf.zero.widget;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.elf.zero.app.AbsLinearLayout;
import com.elf.zero.app.ViewWrapper;

import java.util.ArrayList;
import java.util.List;

/**
 * 多层级选择器
 */
public abstract class MultipleLevelPicker<T> extends AbsLinearLayout {

    private List<LevelBean<T>> levelBeanList;
//    private int padding = 30;
    private int maxLevel = 3;

    private DisplayNameListener<T> listener;

    public MultipleLevelPicker(Context context) {
        this(context, null);
    }

    public MultipleLevelPicker(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected int getLayoutResId() {
        return 0;
    }

    @Override
    protected void initView(AttributeSet attrs) {
        setPadding(10, 0, 10, 0);
        setOrientation(HORIZONTAL);
        levelBeanList = new ArrayList<>();
        listener = new DisplayNameListener<T>() {
            @Override
            public String displayName(T item) {
                return getDisplayName(item);
            }
        };
    }

    public void loadData() {
        addLevel(0, null);
    }

    private void addLevel(int level, T parent) {

        List<Animator> animatorList = new ArrayList<>();

        List<T> items = createList(level, parent);

        final LevelBean<T> levelBean;
        if (levelBeanList.size() <= level) {
            int width = (getMeasuredWidth() - 10 * 2 - 10 * level) / (level + 1);

            if (level > 0) {
                int loop = level;
                while (loop > 0) {
                    View view = levelBeanList.get(loop - 1).listView;
                    int startWidth = view.getMeasuredWidth();
                    animatorList.add(ObjectAnimator.ofInt(new ViewWrapper(view), "width", startWidth, width));
                    loop--;
                }
            }

            levelBean = createLevelBean(level);
            LinearLayout.LayoutParams layoutParams =
                    new LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT);

            if (level > 0) {
                View divider = new View(getContext());
                divider.setBackgroundColor(Color.TRANSPARENT);
                addView(divider, 10, ViewGroup.LayoutParams.MATCH_PARENT);
            }
            addView(levelBean.listView, layoutParams);
            levelBeanList.add(levelBean);
        } else {
            levelBean = levelBeanList.get(level);
        }

        levelBean.adapter.clear();
        if (items != null) {
            levelBean.adapter.addAll(items);
        }
        for (int i = level + 1; i < levelBeanList.size(); i++) {
            levelBeanList.get(i).adapter.clear();
        }

        for (Animator animator : animatorList) {
            animator.start();
        }
    }

    private LevelBean<T> createLevelBean(final int level) {

        final ListViewAdapter<T> adapter = new ListViewAdapter<>(getContext(), listener);
        ListView listView = new ListView(getContext());
        listView.setVerticalScrollBarEnabled(false);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                adapter.setSelectedIndex(position);
                if (level < maxLevel - 1) {
                    addLevel(level + 1, adapter.getItem(position));
                } else {
                    selectedItem(adapter.getItem(position));
                }
            }
        });

        final LevelBean<T> levelBean = new LevelBean<>();
        levelBean.level = level;
        levelBean.adapter = adapter;
        levelBean.listView = listView;
        return levelBean;
    }

    protected abstract String getDisplayName(T item);

    protected abstract List<T> createList(int level, T item);

    protected abstract void selectedItem(T item);

    public int getMaxLevel() {
        return maxLevel;
    }

    public void setMaxLevel(int maxLevel) {
        this.maxLevel = maxLevel;
    }

    private static class LevelBean<T> {
        public int level;
        public ListView listView;
        public ListViewAdapter<T> adapter;
    }

    private static class ListViewAdapter<T> extends ArrayAdapter<T> {

        private LayoutInflater inflater;
        private int selectedIndex = -1;

        private DisplayNameListener<T> listener;

        private ListViewAdapter(@NonNull Context context, DisplayNameListener<T> listener) {
            super(context, 0);
            inflater = LayoutInflater.from(context);
            this.listener = listener;
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            if (convertView == null) {
                convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
            }

            TextView textView = (TextView) convertView;
            textView.setGravity(Gravity.CENTER);
            textView.setText(listener.displayName(getItem(position)));
            textView.setTextColor(position == selectedIndex ? Color.RED : Color.BLACK);
            return convertView;
        }

        private void setSelectedIndex(int index) {
            selectedIndex = index;
            notifyDataSetChanged();
        }

        public int getSelectedIndex() {
            return selectedIndex;
        }

        @Override
        public void clear() {
            super.clear();
            selectedIndex = -1;
        }
    }

    public interface DisplayNameListener<T> {
        String displayName(T item);
    }
}
